package com.example.myskin.views;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import com.example.lib_skin.SkinViewSupport;
import com.example.lib_skin.utils.SkinResources;
import com.example.myskin.R;

import java.lang.reflect.Type;
import java.sql.Types;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;

/**
 * 创建者：voodoo_jie
 * <br>创建时间：2021/3/6 17:53
 * <br>功能描述：仿华为时钟
 */
public class HuaWeiClock extends View implements SkinViewSupport {

    private int backgroundColor; // 背景颜色
    private int secondLineColor; // 秒针竖线的颜色
    private int secondPointColor; // 秒针红色点的颜色
    private int timeColor; // 时间的颜色
    private String timeTextTypefac; // 时间的颜色
    private int widthBg; // 背景宽度
    private int heightBg; // 背景高度

    private int watchRadius; // 钟表半径

    private static final int LINE_MAX_LENGTH = 60; // 线最长的长度
    private static final int LINE_MIN_LENGTH = 30; // 线最短的长度
    private static final int LINE_COUNT = 120; // 秒刻度白线的数量
    private static final int ONE_LINE_ANGLE = 360 / LINE_COUNT; // 每根针占的角度
    private float angle; // 秒针的角度

    private static final int SECOND_POINT_RADIUS = 20; // 秒针红点的半径

    private String time = "00:00";

    private static final int LONG_LINE_COUNT = 7; // 长于普通秒针刻度的驼峰一侧的条数
    private static final int LONG_LINES_ANGLE = ONE_LINE_ANGLE * LONG_LINE_COUNT; // 一侧7根长针的角度

    private Paint backgroundPaint; // 背景画笔
    private Paint secondLinePaint; // 秒线画笔
    private Paint secondPointPaint; // 秒圆点画笔
    private Paint timePaint; // 展示时间的画笔
    private Paint timePaintText; // 展示时间的画笔
    Context context;

    public HuaWeiClock(Context context) {
        this(context, null);
    }

    public HuaWeiClock(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public HuaWeiClock(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HuaWeiClock);
        backgroundColor = typedArray.getColor(R.styleable.HuaWeiClock_huaWeiClockBackgroundColor, Color.parseColor("#003560"));
        secondLineColor = typedArray.getColor(R.styleable.HuaWeiClock_huaWeiClockSecondLineColor, Color.WHITE);
        secondPointColor = typedArray.getColor(R.styleable.HuaWeiClock_huaWeiClockSecondPointColor, Color.parseColor("#CE3228"));
        timeColor = typedArray.getColor(R.styleable.HuaWeiClock_huaWeiClockTimeColor, Color.WHITE);
        timeTextTypefac = typedArray.getString(R.styleable.HuaWeiClock_huaWeiClockTimeTextTypeface);
        typedArray.recycle();
        initPaint();
        startTime();
    }

    /**
     * 初始化画笔
     */
    private void initPaint() {
        backgroundPaint = new Paint(); // 背景画笔
        backgroundPaint.setAntiAlias(true); // 背景画笔
        backgroundPaint.setColor(backgroundColor);
        backgroundPaint.setStyle(Paint.Style.FILL);

        secondLinePaint = new Paint(); // 秒线画笔
        secondLinePaint.setAntiAlias(true); // 秒线画笔
        secondLinePaint.setColor(secondLineColor);
        secondLinePaint.setStyle(Paint.Style.STROKE);
        secondLinePaint.setStrokeWidth(3);

        secondPointPaint = new Paint(); // 秒圆点画笔
        secondPointPaint.setAntiAlias(true); // 秒圆点画笔
        secondPointPaint.setColor(secondPointColor);
        secondPointPaint.setStyle(Paint.Style.FILL);

        timePaint = new Paint(); // 展示时间的画笔
        timePaint.setAntiAlias(true); // 展示时间的画笔
        timePaint.setColor(timeColor);
        timePaint.setStyle(Paint.Style.FILL);

    }

    /**
     * 获取时间，并通过RxJava实现动画
     */
    @SuppressLint("CheckResult")
    private void startTime() {
        // 延时0秒后每隔100毫秒，刷新一次UI
        final SimpleDateFormat minuteFormat = new SimpleDateFormat("HH:mm");
        Observable.interval(0, 80, TimeUnit.MILLISECONDS)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new io.reactivex.functions.Consumer<Long>() {
                    @Override
                    public void accept(Long aLong) throws Exception {
                        Calendar calendar = Calendar.getInstance();
                        angle = (float) (calendar.get(Calendar.SECOND) * 1000 + calendar.get(Calendar.MILLISECOND)) * 6 / 1000f;
                        time = minuteFormat.format(calendar.getTime());
                        postInvalidate();
                    }
                });
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = 0;
        int height = 0;
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        switch (widthMode) {
            case MeasureSpec.AT_MOST:
                width = widthSize * 3 / 4;
                break;
            case MeasureSpec.EXACTLY:
                width = widthSize;
                break;
            case MeasureSpec.UNSPECIFIED:
                break;
            default:
                break;
        }
        switch (heightMode) {
            case MeasureSpec.AT_MOST:
                height = heightSize / 2;
                break;
            case MeasureSpec.EXACTLY:
                height = heightSize;
                break;
            case MeasureSpec.UNSPECIFIED:
                break;
            default:
                break;
        }
        widthBg = width;
        heightBg = height;
        watchRadius = height * 2 / 5;
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        drawBg(canvas);
        drawTickMark(canvas);
        drawSecondPoint(canvas);
        drawTime(canvas);
    }

    /**
     * 绘制背景
     *
     * @param canvas 画板
     */
    private void drawBg(Canvas canvas) {
        RectF rectBg = new RectF(0, 0, widthBg, heightBg);
        canvas.drawRect(rectBg, backgroundPaint);
    }

    /**
     * 绘制刻度线
     *
     * @param canvas 画板
     */
    private void drawTickMark(Canvas canvas) {
        for (int i = 0; i < LINE_COUNT; i++) {
            //角度差的绝对值
            float absoluteValue = Math.abs(i * ONE_LINE_ANGLE - angle);
            //求  刻度针线 和 秒针 之间的角度（小于180度）
            float differenceAngle = absoluteValue <= 180 ? absoluteValue : 360 - absoluteValue;
            //大于七根长线刻度的线，那么长度固定
            if (differenceAngle > LONG_LINES_ANGLE) {
                canvas.drawLine((float) widthBg / 2, (float) heightBg / 2 - watchRadius, (float) widthBg / 2, (float) heightBg / 2 - watchRadius + LINE_MIN_LENGTH, secondLinePaint);
                canvas.rotate(3, (float) widthBg / 2, (float) heightBg / 2);
            } else {
                canvas.drawLine((float) widthBg / 2, (float) heightBg / 2 - watchRadius - (1 - differenceAngle / LONG_LINES_ANGLE) * (LINE_MAX_LENGTH - LINE_MIN_LENGTH), (float) widthBg / 2, (float) heightBg / 2 - watchRadius + LINE_MIN_LENGTH, secondLinePaint);
                canvas.rotate(3, (float) widthBg / 2, (float) heightBg / 2);
            }
        }
    }

    /**
     * 绘制秒表的红点
     *
     * @param canvas 画布
     */
    private void drawSecondPoint(Canvas canvas) {
        int secondPointRadiusBig = watchRadius - LINE_MIN_LENGTH - SECOND_POINT_RADIUS - 20;
        double pointAngle = angle * Math.PI / 180;
        canvas.drawCircle((float) (widthBg / 2 + secondPointRadiusBig * Math.sin(pointAngle)), (float) (heightBg / 2 - secondPointRadiusBig * Math.cos(pointAngle)), SECOND_POINT_RADIUS, secondPointPaint);
    }


    /**
     * 绘制时间显示
     *
     * @param canvas 画布
     */
    private void drawTime(Canvas canvas) {
        timePaint.setTextSize((float) widthBg / 7);

        Rect bounds = new Rect();
        timePaint.getTextBounds(time, 0, time.length(), bounds);
        Paint.FontMetricsInt fontMetrics = timePaint.getFontMetricsInt();
        int baseline = (getMeasuredHeight() - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;
        canvas.drawText(time, (float) getMeasuredWidth() / 2 - (float) bounds.width() / 2, baseline, timePaint);
    }

    @Override
    public void applySkin() {
        if (backgroundColor != 0) {
            int color = SkinResources.getInstance().getColor(R.color.huaWeiClockBackgroundColor);
            backgroundPaint.setColor(color);
            invalidate();
        }
        if (secondLineColor != 0) {
            int color = SkinResources.getInstance().getColor(R.color.huaWeiClockSecondLineColor);
            secondLinePaint.setColor(color);
            invalidate();
        }
        if (secondPointColor != 0) {
            int color = SkinResources.getInstance().getColor(R.color.huaWeiClockSecondPointColor);
            secondPointPaint.setColor(color);
            invalidate();
        }
        if (timeColor != 0) {
            int color = SkinResources.getInstance().getColor(R.color.huaWeiClockTimeColor);
            timePaint.setColor(color);
            invalidate();
        }
        if (TextUtils.isEmpty(timeTextTypefac)) {
            Typeface typeface = SkinResources.getInstance().getTypeface(R.string.typeface_3);
            Log.d("字体=typeface=", timeTextTypefac);
            timePaint.setTypeface(typeface);
            invalidate();
        }
    }
}